using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections;
using System.Linq;
using Windy.OpenLink.Contracts;

namespace Windy.OpenLink.Collections
{
    public class NameCollection<T> :
        INameCollection<T>,
        IOwnerableObject<T>,
        ICollection<string>,
        IEnumerable<string>,
        IEnumerable,
        INotifyPropertyChanged,
        INotifyCollectionChanged
    {
        #region Constructors
        
        public NameCollection(T owner)
        {
            this.Owner = owner;
            Names = new HashSet<string>();
        }

        public NameCollection(T owner, params string[] names)
        {
            this.Owner = owner;
            Names = new HashSet<string>(names);
        }

        #endregion

        #region Fields
        
        protected HashSet<string> Names;
        
        #endregion

        #region ICollection<string> Members

        public bool Add(string newName)
        {
            bool result = Names.Add(newName);

            if (result)
                ItemAdded(newName);

            return result;
        }

        void ICollection<string>.Add(string item)
        {
            this.Add(item);
        }

        public void Clear()
        {
            Names.Clear();
            ItemsCleared();
        }

        public bool Contains(string name)
        {
            return Names.Contains(name);
        }

        public void CopyTo(string[] array, int arrayIndex)
        {
            Names.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return Names.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(string item)
        {
            bool result = Names.Remove(item);

            if (result)
                ItemRemoved(item);

            return result;
        }

        #endregion

        #region IEnumerable<string> Members

        public IEnumerator<string> GetEnumerator()
        {
            return Names.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void Notify(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #region INotifyCollectionChanged Members

        public event NotifyCollectionChangedEventHandler CollectionChanged;
        protected virtual void NotifyCollection(NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, e);
            }
        }

        #region NotifyCollection Usability Overloads

        protected void NotifyCollection(NotifyCollectionChangedAction action, object item)
        {
            this.NotifyCollection(new NotifyCollectionChangedEventArgs(action, item));
        }

        protected void NotifyCollection(NotifyCollectionChangedAction action, IList items)
        {
            this.NotifyCollection(new NotifyCollectionChangedEventArgs(action, items));
        }

        #endregion

        #region Overrides Collection Members
        protected const int InvalidIndex = -1;
        protected virtual void ItemsCleared()
        {
            Notify("Count");
            Notify("Item[]");
            this.NotifyCollection(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
        protected virtual void ItemAdded(string item)
        {
            Notify("Count");
            Notify("Item[]");
            this.NotifyCollection(NotifyCollectionChangedAction.Add, item);
        }
        protected virtual void ItemRemoved(string item)
        {
            Notify("Count");
            Notify("Item[]");
            this.NotifyCollection(NotifyCollectionChangedAction.Remove, item);
        }
        #endregion

        #endregion

        #region IOwnerableObject<T> Members

        public T Owner { get; protected set; }

        #endregion

        #region IOwnerableObject Members

        dynamic IOwnerableObject.Owner { get { return this.Owner; } }

        #endregion
    }
}